package com.tea.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tea.Model.*;
import com.tea.Model.dto.*;
import com.tea.Model.vo.OrderDetailVO;
import com.tea.Model.vo.OrderGoodsDetailVO;
import com.tea.Model.vo.OrderListVO;
import com.tea.config.wx.WxMaConfiguration;
import com.tea.config.wx.WxPayConfig;
import com.tea.constans.OrderStatusConstants;
import com.tea.mapper.GoodsSpecRelationMapper;
import com.tea.mapper.OrderMapper;
import com.tea.mapper.StoreInfoMapper;
import com.tea.utils.Result;
import com.tea.utils.SecurityUtils;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.core.util.PemUtil;
import com.wechat.pay.java.service.partnerpayments.jsapi.model.Transaction;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.ibatis.executor.BatchResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StreamUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.PrivateKey;
import java.time.LocalDateTime;
import java.util.*;

import static com.tea.constans.OrderStatusConstants.*;

@Service
@Slf4j
public class OrderService extends ServiceImpl<OrderMapper, Order> {

    @Resource
    private GoodsSpecService goodsSpecService;
    @Resource
    private GoodsSpecRelationMapper goodsSpecRelationMapper;
    @Resource
    private GoodsService goodsService;
    @Resource
    private StoreInfoMapper storeInfoMapper;
    @Resource
    private WxPayConfig wxPayConfig;
    @Resource
    private WxMaConfiguration  wxMaConfiguration;

    @Resource
    private JsapiServiceExtension jsapiService;
    @Resource
    private WxShippingService wxShippingService;
    @Resource
    private DeliveryCompanyService deliveryCompanyService;

    // 阿里云物流查询API配置
    @Value("${aliyun.logistics.host}")
    private String logisticsHost;
    
    @Value("${aliyun.logistics.path}")
    private String logisticsPath;
    
    @Value("${aliyun.logistics.app-code}")
    private String logisticsAppCode;

    @Transactional
    public Result<?> createOrder(OrderAddDTO request) {


        String outTradeNo = RandomUtil.randomNumbers(8);

        //1.根据规格id查价格信息，结合数量计算价格，并检查库存
        List<GoodsOrderDTO> specWithNum = request.getSpecWithNum();

        ArrayList<Long> specIds = new ArrayList<>();
        for (GoodsOrderDTO goodsOrderDTO : specWithNum) {
            specIds.add(goodsOrderDTO.getSpecId());
        }
        QueryWrapper<GoodsSpec> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", specIds);
        List<GoodsSpec> goodsSpecList = goodsSpecService.list(queryWrapper);
        
        // 检查库存并计算价格
        BigDecimal sumPrice = new BigDecimal("0.00");
        for (GoodsOrderDTO goodsOrderDTO : specWithNum) {
            for (GoodsSpec goodsSpec : goodsSpecList) {
                if (Objects.equals(goodsSpec.getId(), goodsOrderDTO.getSpecId())) {
                    // 获取商品信息检查库存
                    Goods goods = goodsService.getById(goodsSpec.getGoodsId());
                    if (goods == null) {
                        return Result.error("商品不存在");
                    }
                    
                    // 检查规格库存是否充足
                    if (goodsSpec.getStockNum() == null || goodsSpec.getStockNum() <= 0) {
                        return Result.error("商品[" + goods.getName() + "]规格[" + goodsSpec.getSpecRemark() + "]库存不足");
                    }
                    
                    if (goodsSpec.getStockNum() < Long.parseLong(goodsOrderDTO.getNumber())) {
                        return Result.error("商品[" + goods.getName() + "]规格[" + goodsSpec.getSpecRemark() + "]库存不足，当前库存:" + goodsSpec.getStockNum());
                    }
                    
                    BigDecimal price = goodsSpec.getPrice().multiply(new BigDecimal(goodsOrderDTO.getNumber()));
                    sumPrice = sumPrice.add(price);
                }
            }
        }

        //外送订单需要计算配送费
        if (request.getShippingMethod().equals("0")) {
            // 计算配送费
            BigDecimal postage = new BigDecimal("0.0");
            BigDecimal FREE_POSTAGE_THRESHOLD = new BigDecimal("50.0");
            BigDecimal REMOTE_AREA_POSTAGE = new BigDecimal("20.0");
            BigDecimal NORMAL_AREA_POSTAGE = new BigDecimal("10.0"); // 新增常量表示非偏远地区邮费

            // 内蒙古、新疆、西藏、青海、海南的邮编前缀
            List<String> REMOTE_AREA_PREFIXES = Arrays.asList(
                    "01", "02", "83", "85", "57"
            );

            // 先判断postcode是不是偏远地区
            String postcode = request.getPostcode();
            if (postcode == null || postcode.length() < 2) {
                return Result.error("请输入正确的邮编");
            }

            // 检查邮编是否属于偏远地区
            boolean isRemoteArea = REMOTE_AREA_PREFIXES.stream()
                    .anyMatch(prefix -> postcode.startsWith(prefix));

            // 计算邮费
            if (isRemoteArea) {
                // 偏远地区固定20元运费
                postage = REMOTE_AREA_POSTAGE;
                log.info("偏远地区，固定20元运费");
                log.info("订单总价：{}，偏远地区，固定20元运费", sumPrice);
            } else if (sumPrice.compareTo(FREE_POSTAGE_THRESHOLD) < 0) {
                // 非偏远地区且订单金额少于50元，邮费10元
                postage = NORMAL_AREA_POSTAGE;
                log.info("非偏远地区，订单金额 {} 少于50元，收取10元运费", sumPrice);
            } else {
                // 非偏远地区且订单金额超过或等于50元，免邮费
                log.info("非偏远地区，订单金额 {} 满50元，免邮费", sumPrice);
            }
            // 最终把配送费加到总价格中
            sumPrice = sumPrice.add(postage);
            log.info("订单最终总价：{}", sumPrice);
            request.setShippingFee(String.valueOf(postage));
        } else if (request.getShippingFee().equals("1")) {
            log.info("自提无需配送费，订单最终总价：{}", sumPrice);
            request.setShippingFee(String.valueOf(0));
        }

        //2.写入订单编号、规格id、数量到中间表
        ArrayList<GoodsSpecRelation> goodsSpecRelations = new ArrayList<>();
        for (GoodsOrderDTO goodsOrderDTO : specWithNum) {
            GoodsSpecRelation goodsSpecRelation = new GoodsSpecRelation();
            goodsSpecRelation.setSpecId(goodsOrderDTO.getSpecId());
            goodsSpecRelation.setOrderId(outTradeNo);
            goodsSpecRelation.setNumber(goodsOrderDTO.getNumber());
            goodsSpecRelations.add(goodsSpecRelation);
        }
        List<BatchResult> insert = goodsSpecRelationMapper.insert(goodsSpecRelations);
        if (!insert.isEmpty()) {
            log.info("插入订单商品中间表成功");
        }

        //计算出配送费后，生成预支付参数
        //返回预支付参数
        // 1. 创建预支付请求
        PrepayRequest prepayRequest = new PrepayRequest();
        prepayRequest.setAppid(wxPayConfig.getAppid());
        prepayRequest.setMchid(wxPayConfig.getMerchantid());
        prepayRequest.setDescription("商品描述");
        // 生成唯一订单号
        prepayRequest.setOutTradeNo(outTradeNo);
        prepayRequest.setNotifyUrl(wxPayConfig.getNotifyUrl());
        Amount amount = new Amount();
        log.info("订单总价：{}", sumPrice);
        if (sumPrice.compareTo(BigDecimal.ZERO) > 0) {
            long resultPrice = sumPrice.setScale(2, BigDecimal.ROUND_HALF_UP)
                    .multiply(new BigDecimal("100"))
                    .longValueExact();
            amount.setTotal((int) resultPrice);
            log.info("订单总价，单位为分：{}", resultPrice);
        } else {
            amount.setTotal(0);
        }
        amount.setCurrency("CNY");
        prepayRequest.setAmount(amount);
        log.info("预支付参数提交的订单总价，单位为分：{}", amount.getTotal());
        Payer payer = new Payer();
        payer.setOpenid(SecurityUtils.getUserOpenid());
        prepayRequest.setPayer(payer);

        // 2. 调用微信接口生成预支付订单并返回给前端所需支付参数
        PrepayWithRequestPaymentResponse response = jsapiService.prepayWithRequestPayment(prepayRequest);
        if (response != null) {
            log.info("微信返回的预支付参数：{}", response);
            // 2. 序列化为JSON字符串
            String payParamsJson = JSON.toJSONString(response);
            request.setPayParams(payParamsJson);
        }


        //3、拼装order实体
        Order order = Order.builder()
                .orderNo(outTradeNo)
                .openId(SecurityUtils.getUserOpenid())
                .status("0") //0待支付
                .payParams(request.getPayParams())
                .shippingMethod(request.getShippingMethod())
                .username(request.getUsername())
                .address(request.getAddress())
                .storeId(request.getStoreId())
                .phone(request.getPhone())
                .shippingFee(request.getShippingFee())
                .amount(sumPrice)
                .remark(request.getRemark())
                //根据微信报文确定创建时间，这里先暂定系统时间
                .createTime(LocalDateTime.now())
                .build();

        boolean save = save(order);

        if (!save) {
            return Result.error("创建订单记录失败");
        }
        log.info("插入订单表记录成功");


        //发送订阅消息
        try {
            wxMaConfiguration.send(order);
            log.info("发送订阅消息成功");
        }catch (WxErrorException e){
            log.info("发送订阅消息失败{}", e.getMessage());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return Result.success(response);

    }

    public Result<?> orderList(String status) {

        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("open_id", SecurityUtils.getUserOpenid());
        queryWrapper.orderBy(true, false,
                "CASE WHEN status = '1' THEN 0 ELSE 1 END",
                "create_time"
        );
        if (StrUtil.isNotBlank(status)) {
            queryWrapper.eq("status", status);
        }
        List<Order> list = list(queryWrapper);
        //查规格id.再去商品表查主图链接
        ArrayList<OrderListVO> orderListVOS = new ArrayList<>();
        for (Order order : list) {
            OrderListVO orderListVO = new OrderListVO();
            BeanUtil.copyProperties(order, orderListVO);
            orderListVOS.add(orderListVO);
        }
        //1.去订单规格中间表拿规格id 2.根据规格Id去商品规格表拿商品id 3.根据商品id去商品表拿封面图链接
        for (OrderListVO order : orderListVOS) {
            try {
                QueryWrapper<GoodsSpecRelation> goodsSpecQueryWrapper = new QueryWrapper<>();
                goodsSpecQueryWrapper.eq("order_id", order.getOrderNo());
                List<GoodsSpecRelation> goodsSpecRelations = goodsSpecRelationMapper.selectList(goodsSpecQueryWrapper);
                
                // 检查订单规格关系是否存在
                if (goodsSpecRelations == null || goodsSpecRelations.isEmpty()) {
                    log.warn("订单 {} 没有找到商品规格关系", order.getOrderNo());
                    order.setImage(""); // 设置默认图片或空字符串
                    continue;
                }
                
                QueryWrapper<GoodsSpec> goodsSpecQueryWrapper1 = new QueryWrapper<>();
                goodsSpecQueryWrapper1.eq("id", goodsSpecRelations.get(0).getSpecId());
                GoodsSpec goodsSpec = goodsSpecService.getOne(goodsSpecQueryWrapper1);
                
                // 检查商品规格是否存在
                if (goodsSpec == null) {
                    log.warn("订单 {} 的商品规格不存在，规格ID: {}", order.getOrderNo(), goodsSpecRelations.get(0).getSpecId());
                    order.setImage(""); // 设置默认图片或空字符串
                    continue;
                }
                
                QueryWrapper<Goods> goodsQueryWrapper = new QueryWrapper<>();
                goodsQueryWrapper.eq("id", goodsSpec.getGoodsId());
                Goods goods = goodsService.getOne(goodsQueryWrapper);
                
                // 检查商品是否存在
                if (goods == null) {
                    log.warn("订单 {} 的商品不存在，商品ID: {}", order.getOrderNo(), goodsSpec.getGoodsId());
                    order.setImage(""); // 设置默认图片或空字符串
                    continue;
                }
                
                // 设置商品封面图片，如果为null则设置为空字符串
                order.setImage(goods.getCoverImage() != null ? goods.getCoverImage() : "");
                
            } catch (Exception e) {
                log.error("处理订单 {} 的商品图片时发生异常", order.getOrderNo(), e);
                order.setImage(""); // 设置默认图片或空字符串
            }
        }


        return Result.success(orderListVOS);
    }

    /**
     * 订单详情
     */
    public Result<?> getOrder(String orderNo) {

        //1.判断订单是否存在
        QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq("order_no", orderNo);
        Order order = getOne(orderQueryWrapper);
        if (order == null) {
            return Result.error("订单不存在");
        }
        //这里需要拿到订单中包含的商品图片链接、规格信息、数量
        //1.由orderNo拿到订单规格中间表数据集合
        QueryWrapper<GoodsSpecRelation> goodsSpecRelationQueryWrapper = new QueryWrapper<>();
        goodsSpecRelationQueryWrapper.eq("order_id", order.getOrderNo());
        List<GoodsSpecRelation> goodsSpecRelations = goodsSpecRelationMapper.selectList(goodsSpecRelationQueryWrapper);
        //2.遍历集合，根据specId去查对于的商品id
        //商品列表集合 1.godsName cover_image 规格描述 单件商品总价
        ArrayList<OrderGoodsDetailVO> orderGoodsDetailVOS = new ArrayList<>();
        for (GoodsSpecRelation goodsSpecRelation : goodsSpecRelations) {
            QueryWrapper<GoodsSpec> goodsSpecQueryWrapper = new QueryWrapper<>();
            goodsSpecQueryWrapper.eq("id", goodsSpecRelation.getSpecId());
            GoodsSpec goodsSpec = goodsSpecService.getOne(goodsSpecQueryWrapper);
            
            // 检查商品规格是否存在
            if (goodsSpec == null) {
                log.warn("商品规格不存在，规格ID: {}", goodsSpecRelation.getSpecId());
                continue;
            }
            
            Goods goods = goodsService.getById(goodsSpec.getGoodsId());
            
            // 检查商品是否存在
            if (goods == null) {
                log.warn("商品不存在，商品ID: {}", goodsSpec.getGoodsId());
                continue;
            }
            
            // 检查价格是否为空，避免空指针异常
            BigDecimal unitPrice = goodsSpec.getPrice() != null ? goodsSpec.getPrice() : BigDecimal.ZERO;
            
            //构建vo对象
            OrderGoodsDetailVO orderGoodsDetailVO = OrderGoodsDetailVO.builder()
                    .id(goods.getId())
                    .name(goods.getName())
                    .coverImage(goods.getCoverImage())
                    .otherImages(goods.getOtherImages())
                    .specRemark(goodsSpec.getSpecRemark())
                    .price(unitPrice)
                    .specId(goodsSpec.getId())
                    .number(goodsSpecRelation.getNumber())
                    .build();
            orderGoodsDetailVOS.add(orderGoodsDetailVO);

        }
        OrderDetailVO orderDetailVO = BeanUtil.copyProperties(order, OrderDetailVO.class);
        orderDetailVO.setGoodsList(orderGoodsDetailVOS);

        //获取支付参数
        String payParamsJson = orderDetailVO.getPayParams();
        log.info("支付参数：{}", payParamsJson);
        if (payParamsJson != null) {
            JSONObject jsonObject = JSON.parseObject(payParamsJson);
            orderDetailVO.setPayParams(jsonObject.toJSONString());
            log.info("支付参数json序列化后：{}", jsonObject);
        }

        String storeId = order.getStoreId();
        if (StrUtil.isNotBlank(storeId)) {
            StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
            orderDetailVO.setStoreInfo(storeInfo);
        } else {
            orderDetailVO.setStoreInfo(null);
        }


        return Result.success(orderDetailVO);
    }

    public Result<?> orderCompletion(String orderNo) {
        QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq("order_no", orderNo);
        Order order = getOne(orderQueryWrapper);
        if (order == null) {
            return Result.error("订单不存在");
        }
        // 更新 Order 对象的 status 属性
        UpdateWrapper<Order> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("order_no", orderNo);
        updateWrapper.set("status", COMPLETED);
        boolean updateResult = update(updateWrapper);
        if (!updateResult) {
            return Result.error("收货失败，请联系管理员");
        }
        return Result.success("收货成功");


    }

    public Object orderTrack(TrackInfoDTO trackInfoDTO) throws IOException {


        String host = "https://kzexpress.market.alicloudapi.com";
        String path = "/api-mall/api/express/query";
        String appcode = "75e0bf7e6dd94c629ccea8a540f300de";
        Map<String, String> querys = new HashMap<>();
        querys.put("expressNo", trackInfoDTO.getExpressNum());

        // 判断是否是顺丰快递 正则表达式：以SF开头，后面跟13位数字，总长度15位
        String regex = "^SF\\d{13}$";
        if (trackInfoDTO.getExpressNum().matches(regex)){

        }
        QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq("express_num", trackInfoDTO.getExpressNum());
        List<Order> list = list(orderQueryWrapper);
        if (list.isEmpty()) {
            return Result.error("该物流信息不存在于某个订单中");
        }
        querys.put("mobile", list.get(0).getPhone().substring(7));

        OkHttpClient client = new OkHttpClient();

        // 构建URL
        HttpUrl.Builder urlBuilder = HttpUrl.parse(host + path).newBuilder();
        for (Map.Entry<String, String> entry : querys.entrySet()) {
            urlBuilder.addQueryParameter(entry.getKey(), entry.getValue());
        }
        String url = urlBuilder.build().toString();

        // 构建请求
        Request request = new Request.Builder()
                .url(url)
                .get()
                .addHeader("Authorization", "APPCODE " + appcode)
                .build();

        Response response = client.newCall(request).execute();
        String responseData = response.body().string();
        System.out.println(responseData);
        return responseData;

    }

    /**
     * 关闭超时订单 暂定12小时扫描一次
     */
    @Scheduled(fixedRate = 12 * 60 * 60 * 1000)
    public void closeTimeoutOrders() {

        QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.eq("status", PENDING_PAYMENT);
        List<Order> pendingOrders = list(orderQueryWrapper);

        for (Order order : pendingOrders) {
            LocalDateTime createTime = order.getCreateTime();
            LocalDateTime timeoutTime = createTime.plusMinutes(15);
            if (LocalDateTime.now().isAfter(timeoutTime)) {
                UpdateWrapper<Order> orderUpdateWrapper = new UpdateWrapper<>();
                orderUpdateWrapper.eq("order_no", order.getOrderNo());
                orderUpdateWrapper.set("status", CLOSED);
                update(orderUpdateWrapper);
                log.info("订单 {} 已超时，状态变更为已关闭", order.getOrderNo());
            }

        }
    }

    public Result<?> orderAll() {
        return Result.success(list());
    }

    public Result<?> updateOrder(Order order) {

        UpdateWrapper<Order> orderUpdateWrapper = new UpdateWrapper<>();
        orderUpdateWrapper.eq("order_no", order.getOrderNo());
        update(order, orderUpdateWrapper);

        return Result.success("更新订单信息成功");
    }

    public Result<?> getShippingFee(String postcode, String orderPrice) {
        // 基础参数校验
        if (postcode == null) {
            return Result.error("请输入邮编");
        }
        if (postcode.length() < 2) {
            return Result.error("请输入正确的邮编");
        }

        // 偏远地区列表
        List<String> REMOTE_AREA_PREFIXES = Arrays.asList(
                "01", "02", "83", "85", "57"
        );
        BigDecimal FREE_POSTAGE_THRESHOLD = new BigDecimal("50.0");
        BigDecimal REMOTE_AREA_POSTAGE = new BigDecimal("20.0");
        BigDecimal NORMAL_AREA_POSTAGE = new BigDecimal("10.0");

        // 判断是否为偏远地区
        boolean isRemoteArea = REMOTE_AREA_PREFIXES.stream()
                .anyMatch(prefix -> postcode.startsWith(prefix));

        // 计算配送费
        BigDecimal shippingFee;
        BigDecimal orderAmount = null;

        if (isRemoteArea) {
            // 偏远地区固定20元
            shippingFee = REMOTE_AREA_POSTAGE;
        } else {
            // 非偏远地区需要判断订单金额
            if (orderPrice == null || orderPrice.trim().isEmpty()) {
                return Result.error("请输入订单金额");
            }

            try {
                orderAmount = new BigDecimal(orderPrice);
            } catch (NumberFormatException e) {
                return Result.error("订单金额格式错误");
            }

            if (orderAmount.compareTo(FREE_POSTAGE_THRESHOLD) >= 0) {
                // 满50包邮
                shippingFee = BigDecimal.ZERO;
            } else {
                // 不满50收取8元
                shippingFee = NORMAL_AREA_POSTAGE;
            }
        }

        return Result.success(shippingFee);
    }

    @Transactional
    public Result<?> wxPayCallback(HttpServletRequest request) throws IOException {


        // 1. 获取请求头参数
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        String nonce = request.getHeader("Wechatpay-Nonce");
        String signature = request.getHeader("Wechatpay-Signature");
        String serialNumber = request.getHeader("Wechatpay-Serial");
        log.info("支付回调请求头参数：{}", timestamp + "|" + nonce + "|" + signature + "|" + serialNumber);
        // 2. 读取请求体
        String body = StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8);
        log.info("支付回调请求体原始数据：{}", body);

        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(serialNumber)
                .nonce(nonce)
                .timestamp(timestamp)
                .signature(signature)
                .body(body)
                .build();
        log.info("验签请求参数：{}", requestParam);

        // 直接指定私钥文件的绝对路径
        File privateKeyFile = new File("/www/wwwroot/app/apiclient_key.pem");
        // 读取私钥内容
        String privateKeyContent = new String(
                Files.readAllBytes(privateKeyFile.toPath()),
                java.nio.charset.StandardCharsets.UTF_8
        );

        // 4. 加载私钥对象
        PrivateKey privateKey = PemUtil.loadPrivateKeyFromString(privateKeyContent);
        NotificationConfig config = new RSAAutoCertificateConfig.Builder()
                .merchantId("1660458229")
                .privateKey(privateKey)
                .merchantSerialNumber("2E167E53896CD7B02C7518700C46A6390950A414")
                .apiV3Key("Wq4c9t7FhJm3p8Lk2s6Gd5Rb7Nx9yP2V")
                .build();
        NotificationParser parser = new NotificationParser(config);

        try {
            // 以支付通知回调为例，验签、解密并转换成 Transaction
            Transaction transaction = parser.parse(requestParam, Transaction.class);
            log.info("解析回调报文结果： {}", transaction);

            // 业务处理：幂等检查 + 库存扣减 + 更新订单状态
            Transaction.TradeStateEnum tradeState = transaction.getTradeState();
            if (tradeState.equals(Transaction.TradeStateEnum.SUCCESS)) {
                // 查询订单，做幂等控制
                QueryWrapper<Order> orderQueryWrapper = new QueryWrapper<>();
                orderQueryWrapper.eq("order_no", transaction.getOutTradeNo());
                Order order = getOne(orderQueryWrapper);
                if (order == null) {
                    return Result.error("订单不存在");
                }

                if (!PENDING_PAYMENT.equals(order.getStatus())) {
                    // 已处理过或非待支付，直接更新交易单号并返回成功（幂等）
                    UpdateWrapper<Order> idempotentUpdate = new UpdateWrapper<>();
                    idempotentUpdate.eq("order_no", transaction.getOutTradeNo());
                    idempotentUpdate.set("transaction_id", transaction.getTransactionId());
                    update(idempotentUpdate);
                    log.info("支付回调幂等：订单{}当前状态为{}，跳过库存扣减", order.getOrderNo(), order.getStatus());
                } else {
                    // 扣减库存：根据订单中间表逐规格减少库存
                    QueryWrapper<GoodsSpecRelation> relWrapper = new QueryWrapper<>();
                    relWrapper.eq("order_id", order.getOrderNo());
                    List<GoodsSpecRelation> relations = goodsSpecRelationMapper.selectList(relWrapper);
                    for (GoodsSpecRelation rel : relations) {
                        SpecStockUpdateDTO dto = new SpecStockUpdateDTO();
                        dto.setSpecId(rel.getSpecId());
                        dto.setOperation("decrease");
                        dto.setQuantity(Long.valueOf(rel.getNumber()));
                        Result<Object> decResult = goodsSpecService.updateSpecStock(dto);
                        if (!decResult.isSuccess()) {
                            log.error("订单{} 规格{} 库存扣减失败：{}", order.getOrderNo(), rel.getSpecId(), decResult.getMessage());
                            return Result.error("库存扣减失败：" + decResult.getMessage());
                        }
                    }
                    log.info("订单{}库存扣减完成", order.getOrderNo());

                    // 更新订单为待发货并写入交易信息
                    UpdateWrapper<Order> orderUpdateWrapper = new UpdateWrapper<>();
                    orderUpdateWrapper.eq("order_no", transaction.getOutTradeNo());
                    orderUpdateWrapper.set("status", "1");
                    orderUpdateWrapper.set("pay_time", LocalDateTime.now());
                    orderUpdateWrapper.set("transaction_id", transaction.getTransactionId());
                    update(orderUpdateWrapper);
                }
            }


        } catch (ValidationException e) {
            // 签名验证失败，返回 401 UNAUTHORIZED 状态码
            log.error("sign verification failed", e);
            return Result.error("sign verification failed");
        }

        return Result.success("处理成功");

    }

    /**
     * 订单发货
     * orderNo 订单号
     * expressNum 快递单号
     * @return 发货结果
     */
    @Transactional
    public Result<?> shipOrder(ShipOrderDTO shipOrderDTO) {

        String orderNo = shipOrderDTO.getOrderNo();
        String expressNum = shipOrderDTO.getExpressNum();

        // 1. 查询订单信息
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_no", orderNo);
        Order order = getOne(queryWrapper);
        
        if (order == null) {
            return Result.error("订单不存在");
        }
        
        if (!PENDING_SHIPMENT.equals(order.getStatus())) {
            return Result.error("订单状态不允许发货，当前状态: " + OrderStatusConstants.getStatusDesc(order.getStatus()));
        }
        
        if (StrUtil.isBlank(order.getTransactionId())) {
            return Result.error("订单缺少微信支付交易单号，无法同步发货信息");
        }
        
        // 2. 通过快递单号查询物流信息获取快递公司名称
        String logisticsCompanyName;
        try {
            logisticsCompanyName = getLogisticsCompanyName(expressNum, order.getPhone());
//            expressCompanyName = ExpressCompanyUtil.getExpressCompanyName(expressNum);
            if (StrUtil.isBlank(logisticsCompanyName)) {
                return Result.error("无法获取快递公司信息，请检查快递单号是否正确");
            }
            log.info("获取到快递公司名称: {}", logisticsCompanyName);
        } catch (Exception e) {
            log.error("查询物流信息异常，快递单号: {}", expressNum, e);
            return Result.error("查询物流信息失败: " + e.getMessage());
        }
        
        // 3. 根据快递公司名称获取编码
        String expressCompany = deliveryCompanyService.getDeliveryIdByName(logisticsCompanyName);
        if (StrUtil.isBlank(expressCompany)) {
            log.warn("未找到快递公司编码，快递公司名称: {}，使用默认编码 OTHER", logisticsCompanyName);
            expressCompany = "OTHER";
        }
        
        // 4. 更新本地订单状态
        UpdateWrapper<Order> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("order_no", orderNo);
        updateWrapper.set("status", SHIPPED);
        updateWrapper.set("express_num", expressNum);
        updateWrapper.set("delivery_time", LocalDateTime.now());
        
        boolean updateResult = update(updateWrapper);
        if (!updateResult) {
            return Result.error("订单状态更新失败");
        }
        
        // 5. 同步发货信息到微信
        try {
            // 构建商品描述
            String itemDesc = buildItemDescription(orderNo);
            
            WxShippingDTO shippingDTO = new WxShippingDTO();
            shippingDTO.setOrderNo(orderNo);
            shippingDTO.setTransactionId(order.getTransactionId());
            shippingDTO.setOpenId(order.getOpenId());
            shippingDTO.setShippingMethod(order.getShippingMethod());
            shippingDTO.setExpressNum(expressNum);
            shippingDTO.setExpressCompany(expressCompany);
            shippingDTO.setItemDesc(itemDesc);

            //调用微信发货Api
            Result<?> wxResult = wxShippingService.uploadShippingInfo(shippingDTO);
            if (!wxResult.isSuccess()) {
                log.warn("微信发货信息同步失败，但本地状态已更新，订单号: {}, 错误: {}", orderNo, wxResult.getMessage());
                return Result.success("发货成功，但微信同步失败: " + wxResult.getMessage());
            }
            
            log.info("订单发货成功，订单号: {}, 快递单号: {}, 快递公司: {}", orderNo, expressNum, logisticsCompanyName);
            
        } catch (Exception e) {
            log.error("同步微信发货信息异常，订单号: {}", orderNo, e);
            return Result.success("发货成功，但微信同步异常: " + e.getMessage());
        }
        
        return Result.success("发货成功");
    }
    
    /**
     * 构建商品描述
     * @param orderNo 订单号
     * @return 商品描述
     */
    private String buildItemDescription(String orderNo) {
        try {
            // 查询订单商品信息，构建描述
            QueryWrapper<GoodsSpecRelation> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("order_id", orderNo);
            List<GoodsSpecRelation> relations = goodsSpecRelationMapper.selectList(queryWrapper);
            
            if (relations.isEmpty()) {
                return "商品";
            }
            
            StringBuilder desc = new StringBuilder();
            for (GoodsSpecRelation relation : relations) {
                try {
                    GoodsSpec spec = goodsSpecService.getById(relation.getSpecId());
                    if (spec != null) {
                        Goods goods = goodsService.getById(spec.getGoodsId());
                        if (goods != null) {
                            desc.append(goods.getName()).append("*").append(relation.getNumber()).append(",");
                        }
                    }
                } catch (Exception e) {
                    log.warn("构建商品描述时查询商品信息失败，规格ID: {}", relation.getSpecId(), e);
                }
            }
            
            String result = desc.toString();
            return result.length() > 0 ? result.substring(0, result.length() - 1) : "商品";
            
        } catch (Exception e) {
            log.error("构建商品描述异常，订单号: {}", orderNo, e);
            return "商品";
        }
    }
    
    /**
     * 通过快递单号查询物流信息获取快递公司名称
     * @param expressNum 快递单号
     * @param phone 手机号
     * @return 快递公司名称
     * @throws IOException IO异常
     */
    private String getLogisticsCompanyName(String expressNum, String phone) throws IOException {
        Map<String, String> querys = new HashMap<>();
        querys.put("expressNo", expressNum);
        
        // 判断是否是顺丰快递，如果是则需要手机号后4位
        String regex = "^SF\\d{13}$";
        if (expressNum.matches(regex) && StrUtil.isNotBlank(phone) && phone.length() >= 4) {
            querys.put("mobile", phone.substring(phone.length() - 4));
        }
        
        OkHttpClient client = new OkHttpClient();
        
        // 构建URL
        HttpUrl.Builder urlBuilder = HttpUrl.parse(logisticsHost + logisticsPath).newBuilder();
        for (Map.Entry<String, String> entry : querys.entrySet()) {
            urlBuilder.addQueryParameter(entry.getKey(), entry.getValue());
        }
        String url = urlBuilder.build().toString();
        
        // 构建请求
        Request request = new Request.Builder()
                .url(url)
                .get()
                .addHeader("Authorization", "APPCODE " + logisticsAppCode)
                .build();
        
        Response response = client.newCall(request).execute();
        String responseData = response.body().string();
        
        log.debug("物流查询API响应: {}", responseData);
        
        // 解析响应获取快递公司名称
        try {
            JSONObject jsonResponse = JSON.parseObject(responseData);
            if (jsonResponse.getBooleanValue("success") && jsonResponse.getIntValue("code") == 200) {
                JSONObject data = jsonResponse.getJSONObject("data");
                if (data != null) {
                    return data.getString("logisticsCompanyName");
                }
            } else {
                log.warn("物流查询API返回失败: {}", jsonResponse.getString("msg"));
            }
        } catch (Exception e) {
            log.error("解析物流查询API响应异常: {}", responseData, e);
        }
        
        return null;
    }
    
}
